<?php

namespace app\service;

use app\model\DelayOrderTaskModel;
use app\tool\SingletonTrait;

class TaskOverdueService
{
    use SingletonTrait;

    public function __construct()
    {
    }

    /**
     * 历史逾期情况统计(固化)
     * @param $param
     * @param int $userId
     * @param int $tenantId
     * @return array
     */
    public function historyOverdueCount($param, int $userId, int $tenantId = 0): array
    {
        $projectId = $param['project_id'] ?? 0;
        $departmentId = $param['department_id'] ?? 0;
        $stepCategoryIdList = param_to_array($param['step_category_id_list'] ?? [], ',', 'intval');
        $startTime = $param['start_time'] ?? 0;
        $endTime = $param['end_time'] ?? 0;
        $taskDelayList = self::dealOverdueHistory($projectId, $departmentId, $stepCategoryIdList, $userId, $startTime, $endTime);

        $res = [];
        foreach ($taskDelayList as $date => $list) {
            $res[] = [
                'project_id' => $projectId,
                'count' => count($list),
                'plan_end_time' => $date,
            ];
        }
        return $res;
    }

    /**
     * 指定时间范围内，任务逾期情况(固化)
     * @param int $projectId
     * @param int $departmentId
     * @param array $stepCategoryIdList
     * @param int $userId
     * @param int $startTime
     * @param int $endTime
     * @return array
     */
    public function dealOverdueHistory(int $projectId, int $departmentId = 0, array $stepCategoryIdList = [], int $userId = 0, int $startTime = 0, int $endTime = 0): array
    {
        $taskIdListSql = TaskService::getTaskListBaseQuery($projectId, $departmentId, $stepCategoryIdList, $userId)->field('task.id')->buildSql();
        $delayModule = ModuleService::getInstance()->byCode('delay_order_task');
        $delayList = DelayOrderTaskModel::join(['review_request' => 'rr'], 'rr.link_id = delay_order_task.id and rr.module_id = ' . $delayModule['id'], 'left')
            ->whereRaw('delay_order_task.task_id in (' . $taskIdListSql . ')')
            ->whereBetween('delay_order_task.original_plan_time', [$startTime, $endTime])
            ->whereRaw('delay_order_task.original_plan_time < rr.reviewed')
            ->where('rr.is_pass', 'yes')
            ->fieldRaw('delay_order_task.task_id'
                . ', array_agg(from_unixtime(delay_order_task.original_plan_time, "%Y-%m-%d")) as plan_end_time'
                . ', array_agg(from_unixtime(rr.reviewed, "%Y-%m-%d")) as reviewed'
                . ', array_agg(from_unixtime(delay_order_task.delay_time, "%Y-%m-%d")) as delay_time')
            ->order('delay_order_task.task_id')
            ->group('delay_order_task.task_id')
            ->select()->toArray();

        $delayCount = [];
        foreach ($delayList as $delay) {
            $taskId = (int)$delay['task_id'];
            $delay['plan_end_time'] = json_decode($delay['plan_end_time'], true);
            $delay['reviewed'] = json_decode($delay['reviewed'], true);
            $delay['delay_time'] = json_decode($delay['delay_time'], true);

            while (!empty($delay['plan_end_time'])) {
                $start = strtotime(array_shift($delay['plan_end_time']));
                $end = strtotime(array_shift($delay['reviewed']));
                if ($start === false || $end === false) {
                    continue;
                }
                if ($end <= $start) {
                    continue; // 提前、当天审核不算逾期
                }
                if ($endTime > $start) {
//                    if ($endTime > $end) {
                    if ($end > $endTime) {
                        continue; // 不在区间不计算
                    }
                    $delayCount[date('Y-m-d', $end)][$taskId] = ['start' => $start, 'end' => $end];
                }
                break;
            }
        }
        return $delayCount;
    }
}
